package expressions;

import java.util.ArrayList;
import java.util.List;
import parsing.Parser;

/**
 * An expression element that has multiple arguments.
 * 
 * When evaluated, subclasses should call evaluate on the children expressions
 * and use that to calculate their result. Subclasses do not need to check
 * whether the number of arguments is correct.
 * 
 * ParentExpressions do not necessarily evaluate all their children, and may
 * evaluate them multiple times.
 */
public abstract class ParentExpression<T> extends Expression<T>
{
    protected List<Expression<T>> children;
    protected int arguments;

    /**
     * Constructs a new ParentExpression that expects to have the given number
     * of arguments.
     */
    public ParentExpression(int arguments)
    {
        children = new ArrayList<Expression<T>>();
        this.arguments = arguments;
    }

    /**
     * Changes the number of arguments this expression expects to receive. This
     * method should be called before buildTree is called to ensure the correct
     * number of arguments.
     */
    public void setArgumentCount(int n)
    {
        arguments = n;
    }

    public List<Expression<T>> getChildren()
    {
        return children;
    }

    public List<T> getEvaluatedChildren(IContext<T> context)
    {
        List<T> result = new ArrayList<T>();

        for (Expression<T> child : children)
            result.add(child.evaluate(context));

        return result;
    }

    /**
     * Adds the correct number of children for this expression.
     * 
     * The parser will throw an error if there are not sufficiently many
     * children, so after this method is called, we can assume that the number
     * of children is equal to the number of arguments.
     */
    @Override
    public void buildTree(Parser<T> parser)
    {
        children.addAll(parser.getArguments(arguments));

        parser.output(this);
    }
}
